opencode-skills-antigravity 1.0.21 → 1.0.23

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "updatedAt": "2026-03-28T16:36:40.669Z",
3
+ "updatedAt": "2026-03-28T18:42:53.951Z",
4
4
  "entries": [
5
5
  ".gitignore",
6
6
  "00-andruia-consultant",
@@ -34,6 +34,17 @@ ENDPOINTS = [
34
34
  ]
35
35
 
36
36
 
37
+ def create_tls_context():
38
+ """Cria contexto TLS restringindo conexoes a TLS 1.2+."""
39
+ context = ssl.create_default_context()
40
+ if hasattr(ssl, "TLSVersion"):
41
+ context.minimum_version = ssl.TLSVersion.TLSv1_2
42
+ else:
43
+ context.options |= getattr(ssl, "OP_NO_TLSv1", 0)
44
+ context.options |= getattr(ssl, "OP_NO_TLSv1_1", 0)
45
+ return context
46
+
47
+
37
48
  def test_tcp_latency(host, port, timeout=5):
38
49
  """Testa latência TCP para um host:port."""
39
50
  try:
@@ -49,7 +60,7 @@ def test_tcp_latency(host, port, timeout=5):
49
60
  def test_tls_handshake(host, port=443, timeout=5):
50
61
  """Testa tempo do handshake TLS."""
51
62
  try:
52
- context = ssl.create_default_context()
63
+ context = create_tls_context()
53
64
  start = time.time()
54
65
  with socket.create_connection((host, port), timeout=timeout) as sock:
55
66
  with context.wrap_socket(sock, server_hostname=host) as ssock:
@@ -1110,9 +1110,9 @@
1110
1110
  }
1111
1111
  },
1112
1112
  "node_modules/path-to-regexp": {
1113
- "version": "0.1.12",
1114
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
1115
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
1113
+ "version": "0.1.13",
1114
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
1115
+ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
1116
1116
  "license": "MIT"
1117
1117
  },
1118
1118
  "node_modules/prebuild-install": {
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "overrides": {
26
26
  "diff": "4.0.4",
27
+ "path-to-regexp": "0.1.13",
27
28
  "qs": "^6.15.0"
28
29
  }
29
30
  }
@@ -1527,9 +1527,9 @@
1527
1527
  "license": "ISC"
1528
1528
  },
1529
1529
  "node_modules/picomatch": {
1530
- "version": "4.0.3",
1531
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
1532
- "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
1530
+ "version": "4.0.4",
1531
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
1532
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
1533
1533
  "dev": true,
1534
1534
  "license": "MIT",
1535
1535
  "engines": {
@@ -23,6 +23,7 @@
23
23
  "react-dom": "^19.2.3"
24
24
  },
25
25
  "overrides": {
26
+ "picomatch": "4.0.4",
26
27
  "rollup": "^4.59.0"
27
28
  }
28
29
  }
@@ -28,11 +28,21 @@ except ImportError:
28
28
  GRAPH_API = "https://graph.facebook.com/v21.0"
29
29
 
30
30
 
31
- def _mask_secret(value: str) -> str:
32
- """Return a masked version of a secret for safe logging."""
33
- if not value or len(value) < 8:
34
- return "***masked***"
35
- return f"{value[:6]}...masked"
31
+ def _redact_json(value):
32
+ """Recursively redact common secret-bearing keys before logging JSON."""
33
+ sensitive_keys = {"authorization", "token", "access_token", "app_secret", "secret"}
34
+
35
+ if isinstance(value, dict):
36
+ redacted = {}
37
+ for key, item in value.items():
38
+ if key.lower() in sensitive_keys:
39
+ redacted[key] = "***redacted***"
40
+ else:
41
+ redacted[key] = _redact_json(item)
42
+ return redacted
43
+ if isinstance(value, list):
44
+ return [_redact_json(item) for item in value]
45
+ return value
36
46
 
37
47
 
38
48
  def send_test(to: str, message: str) -> None:
@@ -84,11 +94,7 @@ def send_test(to: str, message: str) -> None:
84
94
 
85
95
  print()
86
96
  print("Full response:")
87
- # Mask token in response output to prevent credential leakage
88
- response_str = json.dumps(data, indent=2)
89
- if token and token in response_str:
90
- response_str = response_str.replace(token, _mask_secret(token))
91
- print(response_str)
97
+ print(json.dumps(_redact_json(data), indent=2))
92
98
 
93
99
  except httpx.ConnectError:
94
100
  print("Error: Connection failed. Check your internet connection.")
@@ -96,10 +102,8 @@ def send_test(to: str, message: str) -> None:
96
102
  except httpx.TimeoutException:
97
103
  print("Error: Request timed out.")
98
104
  sys.exit(1)
99
- except Exception as e:
100
- # Mask token in error output to prevent credential leakage
101
- safe_err = str(e).replace(token, _mask_secret(token)) if token else str(e)
102
- print(f"Error: {safe_err}")
105
+ except Exception as exc:
106
+ print(f"Error: unexpected {exc.__class__.__name__} while sending the test message.")
103
107
  sys.exit(1)
104
108
 
105
109
 
@@ -47,14 +47,19 @@ def check_env_vars() -> tuple[bool, list[str]]:
47
47
  return len(missing) == 0, missing
48
48
 
49
49
 
50
- def _mask_secret(value: str) -> str:
51
- """Return a masked version of a secret for safe logging."""
52
- if not value or len(value) < 8:
53
- return "***masked***"
54
- return f"{value[:6]}...masked"
50
+ def _format_api_failure(response: httpx.Response) -> dict[str, str]:
51
+ """Return sanitized API failure details without echoing sensitive payloads."""
52
+ try:
53
+ error = response.json().get("error", {})
54
+ except ValueError:
55
+ error = {}
56
+ return {
57
+ "status_code": str(response.status_code),
58
+ "error_code": str(error.get("code", "?")),
59
+ }
55
60
 
56
61
 
57
- def test_api_connection() -> tuple[bool, str]:
62
+ def test_api_connection() -> tuple[bool, dict[str, str]]:
58
63
  """Test connection to WhatsApp Cloud API."""
59
64
  token = os.environ.get("WHATSAPP_TOKEN", "")
60
65
  phone_id = os.environ.get("PHONE_NUMBER_ID", "")
@@ -69,27 +74,26 @@ def test_api_connection() -> tuple[bool, str]:
69
74
 
70
75
  if response.status_code == 200:
71
76
  data = response.json()
72
- return True, (
73
- f"Phone: {data.get('display_phone_number', 'N/A')}\n"
74
- f" Name: {data.get('verified_name', 'N/A')}\n"
75
- f" Status: {data.get('code_verification_status', 'N/A')}\n"
76
- f" Quality: {data.get('quality_rating', 'N/A')}"
77
- )
78
- else:
79
- error = response.json().get("error", {})
80
- return False, f"API Error {error.get('code', '?')}: {error.get('message', 'Unknown')}"
77
+ return True, {
78
+ "phone": str(data.get("display_phone_number", "N/A")),
79
+ "name": str(data.get("verified_name", "N/A")),
80
+ "status": str(data.get("code_verification_status", "N/A")),
81
+ "quality": str(data.get("quality_rating", "N/A")),
82
+ }
83
+
84
+ return False, _format_api_failure(response)
81
85
 
82
86
  except httpx.ConnectError:
83
- return False, "Connection failed. Check your internet connection."
87
+ return False, {"reason": "Connection failed. Check your internet connection."}
84
88
  except httpx.TimeoutException:
85
- return False, "Request timed out after 10 seconds."
86
- except Exception as e:
87
- # Mask token in error output to prevent credential leakage
88
- safe_err = str(e).replace(token, _mask_secret(token)) if token else str(e)
89
- return False, f"Unexpected error: {safe_err}"
89
+ return False, {"reason": "Request timed out after 10 seconds."}
90
+ except Exception as exc:
91
+ return False, {
92
+ "reason": f"Unexpected {exc.__class__.__name__} while contacting the Graph API."
93
+ }
90
94
 
91
95
 
92
- def test_waba_access() -> tuple[bool, str]:
96
+ def test_waba_access() -> tuple[bool, dict[str, str]]:
93
97
  """Test access to WhatsApp Business Account."""
94
98
  token = os.environ.get("WHATSAPP_TOKEN", "")
95
99
  waba_id = os.environ.get("WABA_ID", "")
@@ -104,15 +108,14 @@ def test_waba_access() -> tuple[bool, str]:
104
108
  if response.status_code == 200:
105
109
  data = response.json()
106
110
  count = len(data.get("data", []))
107
- return True, f"WABA accessible. {count} phone number(s) found."
108
- else:
109
- error = response.json().get("error", {})
110
- return False, f"API Error {error.get('code', '?')}: {error.get('message', 'Unknown')}"
111
+ return True, {"count": str(count)}
111
112
 
112
- except Exception as e:
113
- # Mask token in error output to prevent credential leakage
114
- safe_err = str(e).replace(token, _mask_secret(token)) if token else str(e)
115
- return False, f"Error: {safe_err}"
113
+ return False, _format_api_failure(response)
114
+
115
+ except Exception as exc:
116
+ return False, {
117
+ "reason": f"Unexpected {exc.__class__.__name__} while checking WABA access."
118
+ }
116
119
 
117
120
 
118
121
  def main():
@@ -154,23 +157,37 @@ def main():
154
157
 
155
158
  # Check 2: API connection
156
159
  print("[2/3] Testing API connection (Phone Number)...")
157
- api_ok, api_msg = test_api_connection()
160
+ api_ok, api_details = test_api_connection()
158
161
  if api_ok:
159
- print(f" OK - Connected successfully")
160
- print(f" {api_msg}")
162
+ print(" OK - Connected successfully")
163
+ print(f" Phone: {api_details['phone']}")
164
+ print(f" Name: {api_details['name']}")
165
+ print(f" Status: {api_details['status']}")
166
+ print(f" Quality: {api_details['quality']}")
161
167
  else:
162
- print(f" FAIL - {api_msg}")
168
+ if "reason" in api_details:
169
+ print(f" FAIL - {api_details['reason']}")
170
+ else:
171
+ print(" FAIL - API request failed.")
172
+ print(f" HTTP Status: {api_details['status_code']}")
173
+ print(f" Error Code: {api_details['error_code']}")
163
174
  all_ok = False
164
175
 
165
176
  print()
166
177
 
167
178
  # Check 3: WABA access
168
179
  print("[3/3] Testing WABA access...")
169
- waba_ok, waba_msg = test_waba_access()
180
+ waba_ok, waba_details = test_waba_access()
170
181
  if waba_ok:
171
- print(f" OK - {waba_msg}")
182
+ print(" OK - WABA accessible")
183
+ print(f" Phone Numbers Found: {waba_details['count']}")
172
184
  else:
173
- print(f" FAIL - {waba_msg}")
185
+ if "reason" in waba_details:
186
+ print(f" FAIL - {waba_details['reason']}")
187
+ else:
188
+ print(" FAIL - API request failed.")
189
+ print(f" HTTP Status: {waba_details['status_code']}")
190
+ print(f" Error Code: {waba_details['error_code']}")
174
191
  all_ok = False
175
192
 
176
193
  print()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-skills-antigravity",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "OpenCode CLI plugin that automatically downloads and keeps Antigravity Awesome Skills up to date.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",