@mongoui/skills 0.1.7 → 0.1.9
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 +26 -26
- package/skills/flink-flight-api/SKILL.md +63 -63
- package/skills/flink-flight-api/agents/openai.yaml +4 -4
- package/skills/flink-flight-api/references/api-workflows.md +104 -104
- package/skills/flink-flight-api/references/auth-and-credentials.md +136 -136
- package/skills/flink-flight-api/references/endpoint-index.md +92 -92
- package/skills/flink-flight-api/scripts/flink_signed_request.py +188 -188
- package/skills/glink-hotel-api/SKILL.md +148 -70
- package/skills/glink-hotel-api/agents/openai.yaml +4 -4
- package/skills/glink-hotel-api/references/api-workflows.md +164 -106
- package/skills/glink-hotel-api/references/auth-and-credentials.md +144 -157
- package/skills/glink-hotel-api/references/endpoint-index.md +146 -128
- package/skills/glink-hotel-api/references/field-and-enum-notes.md +161 -0
- package/skills/glink-hotel-api/scripts/glink_signed_request.py +199 -188
- package/skills/tmc-whitelabel/SKILL.md +8 -8
|
@@ -1,188 +1,199 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Generate or send signed requests for the Glink open-platform gateway.
|
|
3
|
-
|
|
4
|
-
Examples:
|
|
5
|
-
python scripts/glink_signed_request.py ^
|
|
6
|
-
--method POST ^
|
|
7
|
-
--path /
|
|
8
|
-
--body-json "{\"language\":\"zh-CN\",\"cityCode\":\"1\"}" ^
|
|
9
|
-
--app-key open_app_xxx ^
|
|
10
|
-
--app-secret sk_xxx
|
|
11
|
-
|
|
12
|
-
python scripts/glink_signed_request.py ^
|
|
13
|
-
--method POST ^
|
|
14
|
-
--path /
|
|
15
|
-
--body-json "{}" ^
|
|
16
|
-
--app-key open_app_xxx ^
|
|
17
|
-
--app-secret sk_xxx ^
|
|
18
|
-
--send
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
from __future__ import annotations
|
|
22
|
-
|
|
23
|
-
import argparse
|
|
24
|
-
import hashlib
|
|
25
|
-
import hmac
|
|
26
|
-
import json
|
|
27
|
-
import os
|
|
28
|
-
import sys
|
|
29
|
-
import time
|
|
30
|
-
import urllib.parse
|
|
31
|
-
import urllib.request
|
|
32
|
-
import uuid
|
|
33
|
-
from pathlib import Path
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
parser.
|
|
135
|
-
parser.add_argument("--
|
|
136
|
-
parser.add_argument("--
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
body_bytes=
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
print()
|
|
182
|
-
print(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Generate or send signed requests for the Glink open-platform gateway.
|
|
3
|
+
|
|
4
|
+
Examples:
|
|
5
|
+
python scripts/glink_signed_request.py ^
|
|
6
|
+
--method POST ^
|
|
7
|
+
--path /region/businesses ^
|
|
8
|
+
--body-json "{\"language\":\"zh-CN\",\"cityCode\":\"1\"}" ^
|
|
9
|
+
--app-key open_app_xxx ^
|
|
10
|
+
--app-secret sk_xxx
|
|
11
|
+
|
|
12
|
+
python scripts/glink_signed_request.py ^
|
|
13
|
+
--method POST ^
|
|
14
|
+
--path /search/creditBalance ^
|
|
15
|
+
--body-json "{}" ^
|
|
16
|
+
--app-key open_app_xxx ^
|
|
17
|
+
--app-secret sk_xxx ^
|
|
18
|
+
--send
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import argparse
|
|
24
|
+
import hashlib
|
|
25
|
+
import hmac
|
|
26
|
+
import json
|
|
27
|
+
import os
|
|
28
|
+
import sys
|
|
29
|
+
import time
|
|
30
|
+
import urllib.parse
|
|
31
|
+
import urllib.request
|
|
32
|
+
import uuid
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
|
|
35
|
+
GATEWAY_PREFIX = "/openapi/v1/glink"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def sha256_hex(data: bytes) -> str:
|
|
39
|
+
return hashlib.sha256(data).hexdigest()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def normalize_path(path: str) -> str:
|
|
43
|
+
if not path.startswith("/"):
|
|
44
|
+
path = f"/{path}"
|
|
45
|
+
if path == GATEWAY_PREFIX or path.startswith(f"{GATEWAY_PREFIX}/"):
|
|
46
|
+
return path
|
|
47
|
+
return f"{GATEWAY_PREFIX}{path}"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def parse_query_items(items: list[str]) -> list[tuple[str, str]]:
|
|
51
|
+
pairs: list[tuple[str, str]] = []
|
|
52
|
+
for item in items:
|
|
53
|
+
if "=" not in item:
|
|
54
|
+
raise ValueError(f"invalid query item: {item!r}; expected key=value")
|
|
55
|
+
key, value = item.split("=", 1)
|
|
56
|
+
pairs.append((key, value))
|
|
57
|
+
return pairs
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def canonical_query(pairs: list[tuple[str, str]]) -> str:
|
|
61
|
+
ordered = sorted(pairs, key=lambda item: (item[0], item[1]))
|
|
62
|
+
return "&".join(
|
|
63
|
+
f"{urllib.parse.quote(key, safe='~-._')}={urllib.parse.quote(value, safe='~-._')}"
|
|
64
|
+
for key, value in ordered
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def build_sign_payload(
|
|
69
|
+
method: str,
|
|
70
|
+
path: str,
|
|
71
|
+
query_string: str,
|
|
72
|
+
body_bytes: bytes,
|
|
73
|
+
timestamp: str,
|
|
74
|
+
nonce: str,
|
|
75
|
+
app_key: str,
|
|
76
|
+
) -> str:
|
|
77
|
+
return "\n".join(
|
|
78
|
+
[
|
|
79
|
+
method.upper(),
|
|
80
|
+
path,
|
|
81
|
+
query_string,
|
|
82
|
+
sha256_hex(body_bytes),
|
|
83
|
+
timestamp,
|
|
84
|
+
nonce,
|
|
85
|
+
app_key,
|
|
86
|
+
]
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def sign(secret: str, payload: str) -> str:
|
|
91
|
+
return hmac.new(secret.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def load_body(args: argparse.Namespace) -> bytes:
|
|
95
|
+
if args.body_file:
|
|
96
|
+
return Path(args.body_file).read_bytes()
|
|
97
|
+
if args.body_json is None:
|
|
98
|
+
return b""
|
|
99
|
+
parsed = json.loads(args.body_json)
|
|
100
|
+
return json.dumps(parsed, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def build_url(base_url: str, path: str, query_string: str) -> str:
|
|
104
|
+
base = base_url.rstrip("/")
|
|
105
|
+
url = f"{base}{path}"
|
|
106
|
+
if query_string:
|
|
107
|
+
url = f"{url}?{query_string}"
|
|
108
|
+
return url
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def build_headers(app_key: str, timestamp: str, nonce: str, signature: str, has_body: bool) -> dict[str, str]:
|
|
112
|
+
headers = {
|
|
113
|
+
"Accept": "application/json",
|
|
114
|
+
"X-OP-App-Key": app_key,
|
|
115
|
+
"X-OP-Timestamp": timestamp,
|
|
116
|
+
"X-OP-Nonce": nonce,
|
|
117
|
+
"X-OP-Sign": signature,
|
|
118
|
+
}
|
|
119
|
+
if has_body:
|
|
120
|
+
headers["Content-Type"] = "application/json"
|
|
121
|
+
return headers
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def send_request(method: str, url: str, headers: dict[str, str], body_bytes: bytes, timeout: float) -> tuple[int, str]:
|
|
125
|
+
request = urllib.request.Request(url=url, data=body_bytes or None, headers=headers, method=method.upper())
|
|
126
|
+
try:
|
|
127
|
+
with urllib.request.urlopen(request, timeout=timeout) as response:
|
|
128
|
+
return response.status, response.read().decode("utf-8", errors="replace")
|
|
129
|
+
except urllib.error.HTTPError as exc:
|
|
130
|
+
return exc.code, exc.read().decode("utf-8", errors="replace")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def main() -> int:
|
|
134
|
+
parser = argparse.ArgumentParser(description="Generate or send a signed Glink open-platform request.")
|
|
135
|
+
parser.add_argument("--base-url", default=os.getenv("OPEN_PLATFORM_BASE_URL", "http://127.0.0.1:8671"))
|
|
136
|
+
parser.add_argument("--method", required=True)
|
|
137
|
+
parser.add_argument("--path", required=True, help="Short interface path, such as /search/destination; full gateway paths are also accepted")
|
|
138
|
+
parser.add_argument("--query", action="append", default=[], help="Repeatable key=value query parameter")
|
|
139
|
+
parser.add_argument("--body-json", help="JSON string request body")
|
|
140
|
+
parser.add_argument("--body-file", help="Path to a raw request body file")
|
|
141
|
+
parser.add_argument("--app-key", default=os.getenv("OPEN_PLATFORM_APP_KEY") or os.getenv("OPEN_PLATFORM_OPEN_APP_ID"))
|
|
142
|
+
parser.add_argument("--app-secret", default=os.getenv("OPEN_PLATFORM_APP_SECRET") or os.getenv("OPEN_PLATFORM_OPEN_SECRET"))
|
|
143
|
+
parser.add_argument("--timestamp", default=str(int(time.time())))
|
|
144
|
+
parser.add_argument("--nonce", default=uuid.uuid4().hex)
|
|
145
|
+
parser.add_argument("--send", action="store_true")
|
|
146
|
+
parser.add_argument("--timeout", type=float, default=15.0)
|
|
147
|
+
args = parser.parse_args()
|
|
148
|
+
|
|
149
|
+
if not args.app_key or not args.app_secret:
|
|
150
|
+
print("app key and app secret are required", file=sys.stderr)
|
|
151
|
+
return 2
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
query_pairs = parse_query_items(args.query)
|
|
155
|
+
body_bytes = load_body(args)
|
|
156
|
+
runtime_path = normalize_path(args.path)
|
|
157
|
+
except Exception as exc:
|
|
158
|
+
print(str(exc), file=sys.stderr)
|
|
159
|
+
return 2
|
|
160
|
+
|
|
161
|
+
query_string = canonical_query(query_pairs)
|
|
162
|
+
payload = build_sign_payload(
|
|
163
|
+
method=args.method,
|
|
164
|
+
path=runtime_path,
|
|
165
|
+
query_string=query_string,
|
|
166
|
+
body_bytes=body_bytes,
|
|
167
|
+
timestamp=args.timestamp,
|
|
168
|
+
nonce=args.nonce,
|
|
169
|
+
app_key=args.app_key,
|
|
170
|
+
)
|
|
171
|
+
signature = sign(args.app_secret, payload)
|
|
172
|
+
headers = build_headers(args.app_key, args.timestamp, args.nonce, signature, bool(body_bytes))
|
|
173
|
+
url = build_url(args.base_url, runtime_path, query_string)
|
|
174
|
+
|
|
175
|
+
print("URL:")
|
|
176
|
+
print(url)
|
|
177
|
+
print()
|
|
178
|
+
print("Canonical String:")
|
|
179
|
+
print(payload)
|
|
180
|
+
print()
|
|
181
|
+
print("Headers:")
|
|
182
|
+
print(json.dumps(headers, ensure_ascii=False, indent=2))
|
|
183
|
+
if body_bytes:
|
|
184
|
+
print()
|
|
185
|
+
print("Body:")
|
|
186
|
+
print(body_bytes.decode("utf-8", errors="replace"))
|
|
187
|
+
|
|
188
|
+
if not args.send:
|
|
189
|
+
return 0
|
|
190
|
+
|
|
191
|
+
status, response_text = send_request(args.method, url, headers, body_bytes, args.timeout)
|
|
192
|
+
print()
|
|
193
|
+
print(f"HTTP {status}")
|
|
194
|
+
print(response_text)
|
|
195
|
+
return 0
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
if __name__ == "__main__":
|
|
199
|
+
raise SystemExit(main())
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: tmc-whitelabel
|
|
3
|
-
description: Placeholder skill for TMC Whitelabel.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# TMC Whitelabel
|
|
7
|
-
|
|
8
|
-
内容待补充。
|
|
1
|
+
---
|
|
2
|
+
name: tmc-whitelabel
|
|
3
|
+
description: Placeholder skill for TMC Whitelabel.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# TMC Whitelabel
|
|
7
|
+
|
|
8
|
+
内容待补充。
|