@maptec/cli 1.0.0
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/LICENSE +21 -0
- package/README.md +284 -0
- package/bin/maptec.js +2 -0
- package/dist/chunk-K574OFFK.js +122 -0
- package/dist/chunk-K574OFFK.js.map +1 -0
- package/dist/cli.js +899 -0
- package/dist/cli.js.map +1 -0
- package/dist/store-ZU7HLXCV.js +18 -0
- package/dist/store-ZU7HLXCV.js.map +1 -0
- package/package.json +47 -0
- package/skills/README.md +30 -0
- package/skills/jsapi-skills/README.md +60 -0
- package/skills/jsapi-skills/SKILL.md +145 -0
- package/skills/jsapi-skills/package.json +31 -0
- package/skills/jsapi-skills/references/controls.md +195 -0
- package/skills/jsapi-skills/references/events.md +222 -0
- package/skills/jsapi-skills/references/geocoding.md +184 -0
- package/skills/jsapi-skills/references/map-style.md +123 -0
- package/skills/jsapi-skills/references/map.md +154 -0
- package/skills/jsapi-skills/references/marker.md +136 -0
- package/skills/jsapi-skills/references/operate.md +138 -0
- package/skills/jsapi-skills/references/overlay.md +311 -0
- package/skills/jsapi-skills/references/place-search.md +411 -0
- package/skills/jsapi-skills/references/poi-categories.md +123 -0
- package/skills/jsapi-skills/references/popup.md +146 -0
- package/skills/jsapi-skills/references/re-geocoding.md +183 -0
- package/skills/jsapi-skills/references/routing.md +347 -0
- package/skills/jsapi-skills/references/track.md +240 -0
- package/skills/jsapi-skills/scripts/validate_jsapi_skill.py +160 -0
- package/skills/webapi-skills/README.md +73 -0
- package/skills/webapi-skills/SKILL.md +63 -0
- package/skills/webapi-skills/package.json +32 -0
- package/skills/webapi-skills/references/direction-api.md +175 -0
- package/skills/webapi-skills/references/geocoding.md +195 -0
- package/skills/webapi-skills/references/ip-location.md +87 -0
- package/skills/webapi-skills/references/matrix-api.md +149 -0
- package/skills/webapi-skills/references/nearby-search.md +223 -0
- package/skills/webapi-skills/references/places.md +239 -0
- package/skills/webapi-skills/references/quick-start-cn.md +219 -0
- package/skills/webapi-skills/references/reverse-geocoding.md +157 -0
- package/skills/webapi-skills/references/suggest.md +111 -0
- package/skills/webapi-skills/references/text-search.md +282 -0
- package/skills/webapi-skills/scripts/validate_webapi_skill.py +158 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# 轨迹动画参考
|
|
2
|
+
|
|
3
|
+
当用户要求车辆、人员、设备、船舶等图标沿路线移动,或者要求轨迹回放、暂停、继续、停止、视角跟随、相机过渡、相机绕点旋转时,使用本参考。
|
|
4
|
+
|
|
5
|
+
## 能力范围
|
|
6
|
+
|
|
7
|
+
`maptec-js` 已公开导出以下动画能力:
|
|
8
|
+
|
|
9
|
+
- `Maptec.AnimationManager`
|
|
10
|
+
- `Maptec.AnimationKeyFrameTrack`
|
|
11
|
+
- `Maptec.PointKeyFrameTrack`
|
|
12
|
+
- `Maptec.PolylineKeyFrameTrack`
|
|
13
|
+
- `Maptec.CameraKeyFrameTrack`
|
|
14
|
+
- `Maptec.CameraOrbitKeyFrameTrack`
|
|
15
|
+
|
|
16
|
+
常见组合:
|
|
17
|
+
|
|
18
|
+
- 使用 `PolylineOverlay` 展示完整轨迹线。
|
|
19
|
+
- 使用 `PointKeyFrameTrack` 驱动 `Marker` 或 `CircleOverlay` 沿路径移动。
|
|
20
|
+
- 使用 `PolylineKeyFrameTrack` 驱动 `PolylineOverlay` 逐步增长,展示行驶轨迹。
|
|
21
|
+
- 使用 `CameraKeyFrameTrack` 实现镜头过渡。
|
|
22
|
+
- 使用 `CameraOrbitKeyFrameTrack` 实现相机绕点旋转。
|
|
23
|
+
- 真实道路路径来自路线规划时,先使用 `Driving` / `TruckDriving` 获取路线,再把路线坐标用于动画。
|
|
24
|
+
|
|
25
|
+
## 基础轨迹动画
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
const path = [
|
|
29
|
+
[103.8318, 1.3048],
|
|
30
|
+
[103.8198, 1.3521],
|
|
31
|
+
[103.7764, 1.2966]
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const fullLine = new Maptec.PolylineOverlay({
|
|
35
|
+
positions: path,
|
|
36
|
+
strokeColor: "#c4b5fd",
|
|
37
|
+
strokeWeight: 6,
|
|
38
|
+
strokeOpacity: 0.45
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const animatedLine = new Maptec.PolylineOverlay({
|
|
42
|
+
positions: path,
|
|
43
|
+
strokeColor: "#7c3aed",
|
|
44
|
+
strokeWeight: 6,
|
|
45
|
+
strokeOpacity: 0.95,
|
|
46
|
+
showDirection: true
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const vehicle = new Maptec.Marker({
|
|
50
|
+
position: path[0],
|
|
51
|
+
color: "#ef4444",
|
|
52
|
+
scale: 1.1
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
map.on("load", () => {
|
|
56
|
+
map.addOverlay([fullLine, animatedLine, vehicle]);
|
|
57
|
+
|
|
58
|
+
const lineTrack = new Maptec.PolylineKeyFrameTrack(animatedLine, {
|
|
59
|
+
duration: 8,
|
|
60
|
+
interpolation: "linear"
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const vehicleTrack = new Maptec.PointKeyFrameTrack(vehicle, {
|
|
64
|
+
path,
|
|
65
|
+
duration: 8,
|
|
66
|
+
interpolation: "linear",
|
|
67
|
+
autoRotate: true,
|
|
68
|
+
rotateOffset: 0
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
map.animation.add(lineTrack);
|
|
72
|
+
map.animation.add(vehicleTrack);
|
|
73
|
+
|
|
74
|
+
lineTrack.play();
|
|
75
|
+
vehicleTrack.play();
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 播放控制
|
|
80
|
+
|
|
81
|
+
`PointKeyFrameTrack`、`PolylineKeyFrameTrack` 等轨道继承自 `AnimationKeyFrameTrack`,常用控制方法包括:
|
|
82
|
+
|
|
83
|
+
- `play()`
|
|
84
|
+
- `pause()`
|
|
85
|
+
- `stop()`
|
|
86
|
+
- `reset()`
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const track = new Maptec.PointKeyFrameTrack(vehicle, {
|
|
90
|
+
path,
|
|
91
|
+
duration: 10,
|
|
92
|
+
autoRotate: true,
|
|
93
|
+
rotateOffset: 0
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
map.animation.add(track);
|
|
97
|
+
|
|
98
|
+
playButton.onclick = () => track.play();
|
|
99
|
+
pauseButton.onclick = () => track.pause();
|
|
100
|
+
stopButton.onclick = () => {
|
|
101
|
+
track.stop();
|
|
102
|
+
track.reset();
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 车头朝向
|
|
107
|
+
|
|
108
|
+
`PointKeyFrameTrack` 支持 `autoRotate`。当移动目标是 `Marker` 时,轨道会根据路径方向设置 `marker.rotation`。如果自定义图标素材的“正前方”不是默认方向,用 `rotateOffset` 修正。
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const carTrack = new Maptec.PointKeyFrameTrack(carMarker, {
|
|
112
|
+
path,
|
|
113
|
+
duration: 12,
|
|
114
|
+
interpolation: "linear",
|
|
115
|
+
autoRotate: true,
|
|
116
|
+
rotateOffset: 90
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 视图跟随轨迹
|
|
121
|
+
|
|
122
|
+
可以监听轨道更新,把地图中心移动到当前 Marker 位置。高频调用时建议使用较短 `duration` 或在业务侧做节流。
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
const track = new Maptec.PointKeyFrameTrack(droneMarker, {
|
|
126
|
+
path,
|
|
127
|
+
duration: 12,
|
|
128
|
+
autoRotate: true,
|
|
129
|
+
rotateOffset: 0
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
track.on("update", () => {
|
|
133
|
+
map.easeTo({
|
|
134
|
+
center: droneMarker.position,
|
|
135
|
+
zoom: 14,
|
|
136
|
+
duration: 180
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
map.animation.add(track);
|
|
141
|
+
track.play();
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## 镜头过渡
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
const cameraTrack = new Maptec.CameraKeyFrameTrack([
|
|
148
|
+
{ center: [103.8198, 1.3521], zoom: 11, pitch: 0, bearing: 0 },
|
|
149
|
+
{ center: [103.8519, 1.2903], zoom: 15, pitch: 55, bearing: 120 }
|
|
150
|
+
], {
|
|
151
|
+
duration: 8,
|
|
152
|
+
interpolation: "easeInOut"
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
map.animation.add(cameraTrack);
|
|
156
|
+
cameraTrack.play();
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## 相机绕点旋转
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
const orbitTrack = new Maptec.CameraOrbitKeyFrameTrack({
|
|
163
|
+
duration: 10,
|
|
164
|
+
center: [103.8519, 1.2903],
|
|
165
|
+
radius: 1000,
|
|
166
|
+
startBearing: 0,
|
|
167
|
+
bearingRange: 360,
|
|
168
|
+
iteration: "INFINITE",
|
|
169
|
+
interpolation: "linear"
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
map.animation.add(orbitTrack);
|
|
173
|
+
orbitTrack.play();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## 与路线规划结合
|
|
177
|
+
|
|
178
|
+
如果用户说“沿真实驾车路线移动”“从 A 到 B 轨迹回放”,不能手写虚假路径。应先使用 `Geocode` 转换地址,再用 `Driving.search` 或 `TruckDriving.search` 获取路线。
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const driving = new Maptec.Driving({
|
|
182
|
+
map,
|
|
183
|
+
enableDrawRoute: true,
|
|
184
|
+
strokeColor: "#2563eb",
|
|
185
|
+
strokeWeight: 6
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
driving.search(origin, destination, (error, result) => {
|
|
189
|
+
if (error) {
|
|
190
|
+
console.error("路线规划失败", error);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const route = result?.routes?.[0];
|
|
195
|
+
const path = route?.path || [];
|
|
196
|
+
if (path.length < 2) {
|
|
197
|
+
console.warn("路线结果没有可用于动画的轨迹坐标");
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const vehicle = new Maptec.Marker({ position: path[0] });
|
|
202
|
+
const track = new Maptec.PointKeyFrameTrack(vehicle, {
|
|
203
|
+
path,
|
|
204
|
+
duration: 15,
|
|
205
|
+
autoRotate: true
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
map.addOverlay(vehicle);
|
|
209
|
+
map.animation.add(track);
|
|
210
|
+
track.play();
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 常见意图映射
|
|
215
|
+
|
|
216
|
+
| 用户说法 | 实现方式 |
|
|
217
|
+
|---|---|
|
|
218
|
+
| “让小车图标沿路线移动” | `Marker` + `PointKeyFrameTrack` |
|
|
219
|
+
| “行驶轨迹要显示出来” | `PolylineOverlay` 展示底线,`PolylineKeyFrameTrack` 驱动动画线增长 |
|
|
220
|
+
| “车头一直朝轨迹方向” | `PointKeyFrameTrack({ autoRotate: true, rotateOffset })` |
|
|
221
|
+
| “实现轨迹回放并支持暂停、继续、停止” | 使用轨道的 `play/pause/stop/reset` |
|
|
222
|
+
| “视角跟随车辆/无人机” | 监听轨道 `update`,调用 `map.easeTo({ center })` |
|
|
223
|
+
| “镜头从 A 点飞到 B 点” | `CameraKeyFrameTrack` |
|
|
224
|
+
| “绕建筑或中心点旋转” | `CameraOrbitKeyFrameTrack` |
|
|
225
|
+
|
|
226
|
+
## 注意事项
|
|
227
|
+
|
|
228
|
+
- 不要发明 `Maptec.TrackAnimation`、`Maptec.MoveAnimation` 等未公开类。
|
|
229
|
+
- 不要用手写播放循环替代 JSAPI 已提供的关键帧轨道能力。
|
|
230
|
+
- 真实道路轨迹必须走路线规划结果。
|
|
231
|
+
- `autoRotate` 只会在移动目标是 `Marker` 时更新 `rotation`;若图标方向不对,用 `rotateOffset` 调整。
|
|
232
|
+
- 组件卸载时停止轨道并移除 Marker、PolylineOverlay 等覆盖物。
|
|
233
|
+
|
|
234
|
+
## Agent 规则
|
|
235
|
+
|
|
236
|
+
- 轨迹动画优先使用 `PointKeyFrameTrack`、`PolylineKeyFrameTrack` 和 `map.animation.add(track)`。
|
|
237
|
+
- 轨迹线使用 `PolylineOverlay`,不要生成 `Maptec.Polyline`。
|
|
238
|
+
- 移动图标使用 `Marker`;需要自动朝向时设置 `autoRotate: true` 和合适的 `rotateOffset`。
|
|
239
|
+
- 用户要求真实道路轨迹时,必须先使用路线规划获取路线坐标。
|
|
240
|
+
- 播放器必须提供停止或销毁逻辑,清理时停止轨道并移除轨迹线和移动 Marker。
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate jsapi-skills structure and public-facing guardrails."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
REQUIRED_SKILL_SECTIONS = [
|
|
12
|
+
"安装接入",
|
|
13
|
+
"鉴权",
|
|
14
|
+
"功能列表",
|
|
15
|
+
"能力路由",
|
|
16
|
+
"强约束",
|
|
17
|
+
"输出要求",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
REQUIRED_README_SECTIONS = [
|
|
21
|
+
"简介",
|
|
22
|
+
"功能列表",
|
|
23
|
+
"安装 Skill",
|
|
24
|
+
"如何被 Agent 使用",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
REAL_KEY_PATTERNS = [
|
|
28
|
+
re.compile(r"Maptec\.apiKey\s*=\s*[\"'](?!YOUR_|<你的|YOUR_MAPTEC_KEY)[A-Za-z0-9_-]{16,}[\"']"),
|
|
29
|
+
re.compile(r"Authorization:\s*Bearer\s+(?!\$MAPTEC_JSAPI_KEY)[A-Za-z0-9._-]{16,}"),
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def line_of(text: str, index: int) -> int:
|
|
34
|
+
return text.count("\n", 0, index) + 1
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_frontmatter(skill_md: Path, text: str) -> list[str]:
|
|
38
|
+
findings: list[str] = []
|
|
39
|
+
if not text.startswith("---\n"):
|
|
40
|
+
return [f"{skill_md}:1: missing YAML frontmatter"]
|
|
41
|
+
|
|
42
|
+
end = text.find("\n---", 4)
|
|
43
|
+
if end == -1:
|
|
44
|
+
return [f"{skill_md}:1: malformed YAML frontmatter"]
|
|
45
|
+
|
|
46
|
+
frontmatter = text[4:end]
|
|
47
|
+
if not re.search(r"^name:\s*jsapi-skills$", frontmatter, re.M):
|
|
48
|
+
findings.append(f"{skill_md}:1: missing or invalid name")
|
|
49
|
+
if not re.search(r"^description:\s*.{40,}$", frontmatter, re.M):
|
|
50
|
+
findings.append(f"{skill_md}:1: missing or too-short description")
|
|
51
|
+
return findings
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def find_reference_links(text: str) -> set[str]:
|
|
55
|
+
return set(re.findall(r"references/[A-Za-z0-9_.-]+\.md", text))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def check_skill_md(skill_dir: Path) -> list[str]:
|
|
59
|
+
findings: list[str] = []
|
|
60
|
+
skill_md = skill_dir / "SKILL.md"
|
|
61
|
+
if not skill_md.exists():
|
|
62
|
+
return [f"{skill_md}: missing SKILL.md"]
|
|
63
|
+
|
|
64
|
+
text = skill_md.read_text(encoding="utf-8", errors="ignore")
|
|
65
|
+
findings.extend(check_frontmatter(skill_md, text))
|
|
66
|
+
|
|
67
|
+
for section in REQUIRED_SKILL_SECTIONS:
|
|
68
|
+
if f"## {section}" not in text:
|
|
69
|
+
findings.append(f"{skill_md}:1: missing section '## {section}'")
|
|
70
|
+
|
|
71
|
+
for required in ["不要发明", "需确认", "[lng, lat]", "MAPTEC_JSAPI_KEY"]:
|
|
72
|
+
if required not in text:
|
|
73
|
+
findings.append(f"{skill_md}:1: missing required guardrail '{required}'")
|
|
74
|
+
|
|
75
|
+
for ref in find_reference_links(text):
|
|
76
|
+
if not (skill_dir / ref).exists():
|
|
77
|
+
findings.append(f"{skill_md}:1: missing referenced file {ref}")
|
|
78
|
+
|
|
79
|
+
return findings
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def check_readme(skill_dir: Path) -> list[str]:
|
|
83
|
+
findings: list[str] = []
|
|
84
|
+
readme = skill_dir / "README.md"
|
|
85
|
+
if not readme.exists():
|
|
86
|
+
return [f"{readme}: missing README.md"]
|
|
87
|
+
|
|
88
|
+
text = readme.read_text(encoding="utf-8", errors="ignore")
|
|
89
|
+
for section in REQUIRED_README_SECTIONS:
|
|
90
|
+
if f"## {section}" not in text:
|
|
91
|
+
findings.append(f"{readme}:1: missing section '## {section}'")
|
|
92
|
+
|
|
93
|
+
for ref in find_reference_links(text):
|
|
94
|
+
if not (skill_dir / ref).exists():
|
|
95
|
+
findings.append(f"{readme}:1: missing referenced file {ref}")
|
|
96
|
+
|
|
97
|
+
return findings
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def check_references(skill_dir: Path) -> list[str]:
|
|
101
|
+
findings: list[str] = []
|
|
102
|
+
refs_dir = skill_dir / "references"
|
|
103
|
+
if not refs_dir.exists():
|
|
104
|
+
return [f"{refs_dir}: missing references directory"]
|
|
105
|
+
|
|
106
|
+
refs = sorted(refs_dir.glob("*.md"))
|
|
107
|
+
if not refs:
|
|
108
|
+
return [f"{refs_dir}: no reference files"]
|
|
109
|
+
|
|
110
|
+
for ref in refs:
|
|
111
|
+
text = ref.read_text(encoding="utf-8", errors="ignore")
|
|
112
|
+
if "## Agent 规则" not in text and "## Agent Rules" not in text:
|
|
113
|
+
findings.append(f"{ref}:1: missing Agent 规则 section")
|
|
114
|
+
if "TODO" in text:
|
|
115
|
+
findings.append(f"{ref}:1: unresolved TODO")
|
|
116
|
+
for linked_ref in find_reference_links(text):
|
|
117
|
+
if not (skill_dir / linked_ref).exists():
|
|
118
|
+
findings.append(f"{ref}:1: missing referenced file {linked_ref}")
|
|
119
|
+
|
|
120
|
+
return findings
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def check_key_leaks(skill_dir: Path) -> list[str]:
|
|
124
|
+
findings: list[str] = []
|
|
125
|
+
for path in sorted(skill_dir.rglob("*")):
|
|
126
|
+
if ".git" in path.parts or "node_modules" in path.parts or not path.is_file():
|
|
127
|
+
continue
|
|
128
|
+
if path.suffix not in {".md", ".yaml", ".yml", ".py", ".js", ".ts", ".html"}:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
text = path.read_text(encoding="utf-8", errors="ignore")
|
|
132
|
+
for pattern in REAL_KEY_PATTERNS:
|
|
133
|
+
for match in pattern.finditer(text):
|
|
134
|
+
findings.append(f"{path}:{line_of(text, match.start())}: possible real key or bearer token")
|
|
135
|
+
return findings
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def main(argv: list[str]) -> int:
|
|
139
|
+
skill_dir = Path(argv[1]) if len(argv) > 1 else Path.cwd()
|
|
140
|
+
if not skill_dir.exists():
|
|
141
|
+
print(f"ERROR: {skill_dir} does not exist")
|
|
142
|
+
return 2
|
|
143
|
+
|
|
144
|
+
findings: list[str] = []
|
|
145
|
+
findings.extend(check_skill_md(skill_dir))
|
|
146
|
+
findings.extend(check_readme(skill_dir))
|
|
147
|
+
findings.extend(check_references(skill_dir))
|
|
148
|
+
findings.extend(check_key_leaks(skill_dir))
|
|
149
|
+
|
|
150
|
+
if findings:
|
|
151
|
+
for finding in findings:
|
|
152
|
+
print(finding)
|
|
153
|
+
return 1
|
|
154
|
+
|
|
155
|
+
print("OK: jsapi-skills passes validation")
|
|
156
|
+
return 0
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if __name__ == "__main__":
|
|
160
|
+
raise SystemExit(main(sys.argv))
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# webapi-skills
|
|
2
|
+
|
|
3
|
+
为 AI Agent 提供 Maptec Web Services API 能力的 Skill 集合,覆盖文本检索、周边检索、输入提示、地点详情、地理编码、逆地理编码、路线规划、距离矩阵、IP 定位等服务,并包含 API Key 申请与鉴权签名指引。
|
|
4
|
+
|
|
5
|
+
## 简介
|
|
6
|
+
|
|
7
|
+
`webapi-skills` 把 Maptec Web Services API 能力整理成结构化文档,供 AI Agent 进行能力归类、接口选型、参数约束、鉴权处理、代码生成和代码审查。核心入口是 `SKILL.md`,各项能力的详细规则在 `references/` 目录下。
|
|
8
|
+
|
|
9
|
+
## 功能列表
|
|
10
|
+
|
|
11
|
+
| 能力 | 说明 | 用户示例 |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| 快速接入 | 账号注册、项目创建、API Key 创建、服务授权、首个请求、SK/HMAC 签名 | “我没有 Key,怎么开始调用接口” |
|
|
14
|
+
| 文本检索 | 关键词检索 POI,支持 `query`、`type`、`locationBias`、`locationLimit`、分页、排序、语言、区域 | “搜索新加坡所有咖啡馆” |
|
|
15
|
+
| 周边检索 | 圆形范围周边检索,支持 `locationLimit`、`types`、`resultLimit`、排序、语言、区域 | “乌节路附近 1 公里的餐厅” |
|
|
16
|
+
| 输入提示 | 关键词输入联想提示,支持 `query`、`types`、`locationBias`、`locationLimit`、`resultlimit`、语言、区域 | “输入‘乌节’返回提示词” |
|
|
17
|
+
| 地点详情 | 根据 `placeId` 获取地点详情,支持 `language`、`region` | “获取某个地点的详细信息” |
|
|
18
|
+
| 距离矩阵 | 计算起终点距离与时间矩阵,支持 1xN 与 MxN 限制 | “计算多个起点到多个终点的距离” |
|
|
19
|
+
| 路线规划 | 驾车路线规划,支持起终点、途经点、避让规则、route/leg/step 响应 | “规划 A 到 B 的驾车路线” |
|
|
20
|
+
| IP 定位 | 根据公网 IP 返回位置信息 | “我现在在哪” |
|
|
21
|
+
| 地理编码 | 地址转经纬度,支持 `address`、`components`、location bias、geometry、地址组件 | “把某个地址转换为坐标” |
|
|
22
|
+
| 逆地理编码 | 经纬度转地址,支持 `location`、结果过滤、geometry、地址组件 | “把坐标转换为详细地址” |
|
|
23
|
+
|
|
24
|
+
## 安装 Skill
|
|
25
|
+
|
|
26
|
+
用于将 `webapi-skills` 安装到本机 Agent Skills 目录,供 AI Agent 识别和使用。
|
|
27
|
+
|
|
28
|
+
### (1)通过 npm 包安装
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @maptec/webapi-skills install
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
安装完成后,默认目录为:`~/.agents/skills/webapi-skills`
|
|
35
|
+
|
|
36
|
+
### (2)自定义安装目录
|
|
37
|
+
|
|
38
|
+
支持用环境变量 `MAPTEC_SKILL_INSTALL_DIR` 指定安装父目录:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
MAPTEC_SKILL_INSTALL_DIR=/path/to/skills npx @maptec/webapi-skills install
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### (3)GitHub 开源地址
|
|
45
|
+
|
|
46
|
+
`webapi-skills` 已开源到 GitHub 的 [maptec-api/webapi-skills](https://github.com/maptec-api/webapi-skills) 仓库,可以查看源码、了解目录结构,或在本地按需扩展 Web Services API 能力文档:
|
|
47
|
+
|
|
48
|
+
[https://github.com/maptec-api/webapi-skills](https://github.com/maptec-api/webapi-skills)
|
|
49
|
+
|
|
50
|
+
## Maptec Web Services API 接入
|
|
51
|
+
|
|
52
|
+
业务项目中的接口主机、鉴权格式和 Key 申请流程见 [SKILL.md](SKILL.md)。当前集成示例统一使用测试环境主机 `https://test-api.maptec.com`。不同接口的鉴权格式:
|
|
53
|
+
|
|
54
|
+
- Web Services API 默认使用 `Authorization: YOUR_API_KEY`。
|
|
55
|
+
- 具体接口如在参考文档中另有说明,以对应 `references/*.md` 为准。
|
|
56
|
+
- Secret Key 校验在以上基础上附加 `X-Timestamp` 与 `X-Signature`(对 `apiKey + timestamp + path + query` 做小写 hex HMAC-SHA256)。
|
|
57
|
+
|
|
58
|
+
推荐将 Key 配置为本机环境变量,不要写入源码或粘贴到对话中:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
export MAPTEC_API_KEY="YOUR_API_KEY"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 如何被 Agent 使用
|
|
65
|
+
|
|
66
|
+
Agent 使用本 Skill 时,应遵循以下流程:
|
|
67
|
+
|
|
68
|
+
1. 先根据用户需求归类到功能列表中的一个或多个能力。
|
|
69
|
+
2. 根据 `SKILL.md` 的 Workflow,只读取相关 `references/*.md`,并在需要鉴权/首次调用时读取 `references/quick-start-cn.md`。
|
|
70
|
+
3. 严格保留参考文档中的接口 URL、HTTP 方法、鉴权格式、参数名、枚举值、限制和 JSON 响应结构。
|
|
71
|
+
4. 生成代码前说明命中的能力和使用的接口。
|
|
72
|
+
5. 用户要求实际调用接口时,先检查 `MAPTEC_API_KEY` 是否存在(不打印其值),缺失则先给出申请与配置流程。
|
|
73
|
+
6. 不要发明未文档化的字段或限制,文档未说明时如实说明。
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: webapi-skills
|
|
3
|
+
description: Maptec Web Services API documentation assistant for Search, Geocoding, Reverse Geocoding, Place Details, Nearby Search, Suggest, Directions, Distance Matrix, and IP Location APIs, including API Key setup and quick-start guidance. Use when Codex needs to answer questions, draft integration code, compare request/response fields, validate parameters, guide users without an API Key, configure credentials, sign requests, or explain endpoint usage for these Maptec Web Service APIs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# WebAPI Skills
|
|
7
|
+
|
|
8
|
+
Use this skill to answer Maptec Web Services API questions from bundled references synced from the official website and Yuque documentation.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Identify the requested API or workflow.
|
|
13
|
+
2. Open only the matching reference file from `references/`. Also open `references/quick-start-cn.md` when the user needs setup, credential, authorization, first-call, or signing guidance.
|
|
14
|
+
3. Answer from the reference. Preserve endpoint URLs, HTTP methods, auth format, parameter names, enum values, limits, and JSON response shapes exactly as documented.
|
|
15
|
+
4. When drafting code, use the auth header documented by the relevant reference. Web Services APIs, including IP Location, use `Authorization: <YOUR_API_KEY>`. Do not add `Bearer` unless the specific reference requires it.
|
|
16
|
+
5. Use `https://test-api.maptec.com` as the current base host for integration examples. Treat production host migration as a later environment swap.
|
|
17
|
+
6. If a user asks across APIs, read the relevant files and summarize differences in a table.
|
|
18
|
+
|
|
19
|
+
## API Key Setup
|
|
20
|
+
|
|
21
|
+
When the user wants to call an API but has no key configured:
|
|
22
|
+
|
|
23
|
+
1. Do not stop after reporting that `MAPTEC_API_KEY` is missing. Proactively provide the complete setup flow below in the same response.
|
|
24
|
+
1. Explain that a MapTec developer account is required.
|
|
25
|
+
2. Direct them to register at `https://test-lbs.maptec.com/auth/register` or log in at `https://test-lbs.maptec.com/auth/login`.
|
|
26
|
+
3. Have them create a project in `https://test-lbs.maptec.com/console/project-asset`.
|
|
27
|
+
4. Have them create a Key inside the project and select application restriction type `Rest API (Server)` for Web Services API.
|
|
28
|
+
5. If IP restrictions are needed, tell them to enter server IP/CIDR values without ports; blank means unrestricted.
|
|
29
|
+
6. Have them authorize only the needed services before finishing Key creation.
|
|
30
|
+
7. Recommend setting the key locally as `MAPTEC_API_KEY` instead of pasting it into chat:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export MAPTEC_API_KEY="YOUR_API_KEY"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For questions such as “我现在在哪” or “where am I,” treat the request as an attempt to call IP Location rather than merely a documentation question:
|
|
37
|
+
|
|
38
|
+
1. Check whether `MAPTEC_API_KEY` is available without printing its value.
|
|
39
|
+
2. If it is missing, give the complete account, project, Key, IP restriction, service authorization, and environment-variable setup flow above. Explicitly tell the user to authorize the IP Location service.
|
|
40
|
+
3. Explain that IP Location requires a public IPv4 or IPv6 address as the `ip` request field; a local timezone is not proof of physical location.
|
|
41
|
+
4. After configuration, obtain or ask for the user's public IP as appropriate, then call the IP Location endpoint from `references/ip-location.md` with JSON body `{"ip":"..."}` and the documented `Authorization` header.
|
|
42
|
+
|
|
43
|
+
For Secret Key (SK) verification, read `references/quick-start-cn.md` and include `X-Timestamp` plus `X-Signature`. The signature is lowercase hex HMAC-SHA256 over `apiKey + timestamp + path + query`.
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
- `references/quick-start-cn.md`: account registration, project creation, API Key creation, service authorization, first request, and optional SK/HMAC signing.
|
|
48
|
+
- `references/text-search.md`: Text Search API, `query`, `type`, `locationBias`, `locationLimit`, pagination, rank, language, and region.
|
|
49
|
+
- `references/nearby-search.md`: Nearby Search API, circle `locationLimit`, `types`, `resultLimit`, rank, language, and region.
|
|
50
|
+
- `references/suggest.md`: Suggest API, `query`, `types`, `locationBias`, `locationLimit`, `resultlimit`, language, and region.
|
|
51
|
+
- `references/places.md`: Place Details API, `placeId`, `language`, and `region`.
|
|
52
|
+
- `references/matrix-api.md`: Distance Matrix API, origins/destinations, 1xN and MxN matrix limits.
|
|
53
|
+
- `references/direction-api.md`: Directions API, origin/destination, waypoints, avoid rules, route/leg/step response.
|
|
54
|
+
- `references/ip-location.md`: IP Location API, IP request body and location response.
|
|
55
|
+
- `references/geocoding.md`: Geocoding API, address, components, location bias, geometry, and address components.
|
|
56
|
+
- `references/reverse-geocoding.md`: Reverse Geocoding API, `location`, result filters, geometry, and address components.
|
|
57
|
+
|
|
58
|
+
## Response Guidance
|
|
59
|
+
|
|
60
|
+
- Prefer concise integration-ready answers: endpoint, method, auth, required parameters, example request, and expected response.
|
|
61
|
+
- If a user asks to actually call an API, first check whether `MAPTEC_API_KEY` is available in the local environment without printing it. If it is missing, provide the setup flow above instead of attempting a call.
|
|
62
|
+
- Use the test host consistently even when the source document shows an older `api.maptec.com` or `api.maptech.com` host.
|
|
63
|
+
- Do not invent undocumented fields or limits. Say the reference does not specify them.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@maptec/webapi-skills",
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "Maptec Web Services API Agent Skill package",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"webapi-skills": "bin/webapi-skills.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"SKILL.md",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"references",
|
|
15
|
+
"scripts"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"validate": "python3 scripts/validate_webapi_skill.py ."
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"maptec",
|
|
22
|
+
"webapi",
|
|
23
|
+
"web-services",
|
|
24
|
+
"agent",
|
|
25
|
+
"skill",
|
|
26
|
+
"maps"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|