kcode-pi 0.1.5 → 0.1.7
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/README.md +35 -2
- package/dist/cli/kcode.d.ts +1 -0
- package/dist/cli/kcode.js +27 -4
- package/package.json +1 -1
- package/src/cli/kcode.ts +29 -4
- package/src/official/kingdee-skills.ts +60 -13
- package/src/rules/checker.ts +143 -0
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/SKILL.md +2 -2
- package/vendor/kingdee-skills/ok-cosmic/SKILL.md +52 -101
- package/vendor/kingdee-skills/ok-cosmic/agents/openai.yaml +4 -4
- package/vendor/kingdee-skills/ok-cosmic/manifest.json +21 -20
- package/vendor/kingdee-skills/ok-cosmic/ok-cosmic-intro.html +1 -1
- package/vendor/kingdee-skills/ok-cosmic/rules/a-layer-rules.json +1 -1
- package/vendor/kingdee-skills/ok-cosmic/rules/anti-patterns.md +2 -2
- package/vendor/kingdee-skills/ok-cosmic/rules/coding-preferences.md +4 -4
- package/vendor/kingdee-skills/ok-cosmic/rules/constraints.md +3 -3
- package/vendor/kingdee-skills/ok-cosmic/rules/decision-matrix.md +8 -8
- package/vendor/kingdee-skills/ok-cosmic/rules/intent-routing.md +1 -1
- package/vendor/kingdee-skills/ok-cosmic/rules/post-check.md +19 -18
- package/vendor/kingdee-skills/ok-ksql/SKILL.md +9 -9
- package/vendor/kingdee-skills/ok-ksql/manifest.json +2 -1
- package/vendor/kingdee-skills/ok-ksql/references/ksql-datafix.md +2 -2
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/pattern-matcher.py +0 -336
- package/vendor/kingdee-skills/kingdee-cosmic-reviewer/scripts/review-score-calculator.py +0 -121
- package/vendor/kingdee-skills/ok-cosmic/CHANGELOG.md +0 -295
- package/vendor/kingdee-skills/ok-cosmic/README.md +0 -460
- package/vendor/kingdee-skills/ok-cosmic/requirements.txt +0 -2
- package/vendor/kingdee-skills/ok-cosmic/scripts/config_loader.py +0 -204
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-api-knowledge.py +0 -910
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-basedata-query.py +0 -359
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-config-check.py +0 -181
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-extpoints-query.py +0 -389
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-form-metadata.py +0 -856
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-check.py +0 -262
- package/vendor/kingdee-skills/ok-cosmic/scripts/cosmic-post-lint.py +0 -293
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/__init__.py +0 -2
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/base.py +0 -393
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/resource_check.py +0 -176
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/scene_check.py +0 -375
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/style_check.py +0 -434
- package/vendor/kingdee-skills/ok-cosmic/scripts/lint/verify_check.py +0 -36
- package/vendor/kingdee-skills/ok-cosmic/scripts/route_client.py +0 -186
- package/vendor/kingdee-skills/ok-cosmic/scripts/script_utils.py +0 -40
- package/vendor/kingdee-skills/ok-cosmic/scripts/sqlite_cache.py +0 -142
- package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-commons.jar +0 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/cuslib/kd-cd-cosmic-features.jar +0 -0
- package/vendor/kingdee-skills/ok-cosmic/setup/setup-mac.sh +0 -18
- package/vendor/kingdee-skills/ok-cosmic/setup/setup-windows.bat +0 -53
- package/vendor/kingdee-skills/ok-cosmic/setup/setup.jar +0 -0
- package/vendor/kingdee-skills/ok-ksql/scripts/ksql_lint.py +0 -363
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# SPDX-License-Identifier: NOASSERTION
|
|
3
|
-
"""
|
|
4
|
-
cosmic-extpoints-query.py — Cosmic business extension point query tool.
|
|
5
|
-
|
|
6
|
-
Usage:
|
|
7
|
-
python3 cosmic-extpoints-query.py --config ok-cosmic.json get --keyword 应付
|
|
8
|
-
python3 cosmic-extpoints-query.py --config ok-cosmic.json get 应付
|
|
9
|
-
python3 cosmic-extpoints-query.py --config ok-cosmic.json get --keyword 应付 --full # 需要生成代码/查看示例时使用
|
|
10
|
-
|
|
11
|
-
What it provides:
|
|
12
|
-
1. Online business extension point lookup by keyword
|
|
13
|
-
2. Unified route API resolution with environment-variable fallback
|
|
14
|
-
3. Optional route.openApiSign support for OpenAPI signed URLs
|
|
15
|
-
4. Human-readable summary output by default, with full JSON only for code sample inspection
|
|
16
|
-
5. AI-friendly field: hasSample
|
|
17
|
-
|
|
18
|
-
What it does NOT do:
|
|
19
|
-
- It does not verify Java method signatures by itself; if the full result has no
|
|
20
|
-
clear Java sample code, use cosmic-api-knowledge.py detail to confirm methods
|
|
21
|
-
and parameters
|
|
22
|
-
- It does not generate plugin implementation code
|
|
23
|
-
- It does not infer whether an extension point is suitable for a concrete event
|
|
24
|
-
|
|
25
|
-
Prerequisites:
|
|
26
|
-
- A reachable runtime/route API, configured by ok-cosmic.json / route env / --api-url
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
import argparse
|
|
30
|
-
import json
|
|
31
|
-
import sys
|
|
32
|
-
from typing import Any, Dict, Iterable, List, Optional, Tuple
|
|
33
|
-
|
|
34
|
-
from config_loader import load_project_config
|
|
35
|
-
from route_client import RouteClient, unwrap_route_raw
|
|
36
|
-
from script_utils import FriendlyArgumentParser, run_cli
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def _shorten(text: Any, max_len: int = 80) -> str:
|
|
40
|
-
value = "" if text is None else str(text)
|
|
41
|
-
value = value.replace("\r", " ").replace("\n", " ").strip()
|
|
42
|
-
if len(value) <= max_len:
|
|
43
|
-
return value
|
|
44
|
-
return value[: max_len - 1] + "…"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def _md_escape(text: Any) -> str:
|
|
48
|
-
return _shorten(text).replace("|", "\\|") or "-"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def _pick_value(item: Dict[str, Any], keys: Iterable[str]) -> Any:
|
|
52
|
-
lower_map = {str(k).lower(): v for k, v in item.items()}
|
|
53
|
-
for key in keys:
|
|
54
|
-
if key in item and item.get(key) not in (None, ""):
|
|
55
|
-
return item.get(key)
|
|
56
|
-
value = lower_map.get(key.lower())
|
|
57
|
-
if value not in (None, ""):
|
|
58
|
-
return value
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def _record_has_sample(item: Dict[str, Any]) -> bool:
|
|
63
|
-
sample = item.get("sample")
|
|
64
|
-
if isinstance(sample, str):
|
|
65
|
-
return bool(sample.strip())
|
|
66
|
-
return bool(sample)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def _first_list_from_mapping(data: Dict[str, Any]) -> Tuple[Optional[List[Any]], Optional[Any]]:
|
|
70
|
-
"""
|
|
71
|
-
Try common list wrappers without assuming the exact remote payload shape.
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
- records list, if found
|
|
75
|
-
- total count, if exposed by the wrapper
|
|
76
|
-
"""
|
|
77
|
-
list_keys = (
|
|
78
|
-
"records",
|
|
79
|
-
"rows",
|
|
80
|
-
"items",
|
|
81
|
-
"list",
|
|
82
|
-
"result",
|
|
83
|
-
"values",
|
|
84
|
-
"extPoints",
|
|
85
|
-
"extpoints",
|
|
86
|
-
"data",
|
|
87
|
-
)
|
|
88
|
-
total = (
|
|
89
|
-
data.get("total")
|
|
90
|
-
or data.get("totalCount")
|
|
91
|
-
or data.get("count")
|
|
92
|
-
or data.get("size")
|
|
93
|
-
)
|
|
94
|
-
for key in list_keys:
|
|
95
|
-
value = data.get(key)
|
|
96
|
-
if isinstance(value, list):
|
|
97
|
-
return value, total
|
|
98
|
-
return None, total
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def _looks_like_extpoints_payload(value: Any) -> bool:
|
|
102
|
-
if isinstance(value, list):
|
|
103
|
-
return True
|
|
104
|
-
if not isinstance(value, dict):
|
|
105
|
-
return False
|
|
106
|
-
records, _ = _first_list_from_mapping(value)
|
|
107
|
-
return records is not None
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def _unwrap_route_raw(raw: Dict[str, Any]) -> Dict[str, Any]:
|
|
111
|
-
return unwrap_route_raw(raw, _looks_like_extpoints_payload)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class ExtPointsQuery:
|
|
115
|
-
def __init__(
|
|
116
|
-
self,
|
|
117
|
-
config: Dict[str, Any],
|
|
118
|
-
api_url: Optional[str] = None,
|
|
119
|
-
debug: bool = False,
|
|
120
|
-
):
|
|
121
|
-
self.debug = debug
|
|
122
|
-
route_config = config.get("route", {})
|
|
123
|
-
if not isinstance(route_config, dict):
|
|
124
|
-
route_config = {}
|
|
125
|
-
|
|
126
|
-
self.route_client = RouteClient(
|
|
127
|
-
route_config,
|
|
128
|
-
api_url=api_url,
|
|
129
|
-
debug=debug,
|
|
130
|
-
missing_message=(
|
|
131
|
-
"未配置业务拓展点查询 API。请在 ok-cosmic.json 的 route.apiUrl 中配置统一路由,"
|
|
132
|
-
"或设置 COSMIC_ROUTE_API / COSMIC_RUNTIME_ROUTE_API 环境变量;"
|
|
133
|
-
"临时调试也可使用 --api-url 指定统一路由地址。"
|
|
134
|
-
),
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
def _post(self, payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
138
|
-
return self.route_client.post(payload)
|
|
139
|
-
|
|
140
|
-
@staticmethod
|
|
141
|
-
def _normalize(raw: Dict[str, Any], keyword: str) -> Dict[str, Any]:
|
|
142
|
-
raw_data = raw.get("data")
|
|
143
|
-
records: Optional[List[Any]] = None
|
|
144
|
-
total: Optional[Any] = None
|
|
145
|
-
trace_id = raw.get("traceId")
|
|
146
|
-
|
|
147
|
-
if isinstance(raw_data, list):
|
|
148
|
-
records = raw_data
|
|
149
|
-
elif isinstance(raw_data, dict):
|
|
150
|
-
records, total = _first_list_from_mapping(raw_data)
|
|
151
|
-
trace_id = raw_data.get("traceId") or trace_id
|
|
152
|
-
elif isinstance(raw.get("records"), list):
|
|
153
|
-
records = raw.get("records")
|
|
154
|
-
total = raw.get("total") or raw.get("totalCount") or raw.get("count")
|
|
155
|
-
|
|
156
|
-
if records is None:
|
|
157
|
-
records = []
|
|
158
|
-
|
|
159
|
-
has_sample = any(_record_has_sample(item) for item in records if isinstance(item, dict))
|
|
160
|
-
return {
|
|
161
|
-
"status": "ok",
|
|
162
|
-
"keyword": keyword,
|
|
163
|
-
"traceId": trace_id,
|
|
164
|
-
"total": total,
|
|
165
|
-
"count": len(records),
|
|
166
|
-
"hasSample": has_sample,
|
|
167
|
-
"records": records,
|
|
168
|
-
"data": raw_data,
|
|
169
|
-
"raw": raw,
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
def query(self, keyword: str) -> Dict[str, Any]:
|
|
173
|
-
normalized_keyword = (keyword or "").strip()
|
|
174
|
-
if not normalized_keyword:
|
|
175
|
-
raise ValueError("keyword 不能为空。请传入业务关键词,例如:--keyword 应付")
|
|
176
|
-
|
|
177
|
-
payload = {
|
|
178
|
-
"data": {
|
|
179
|
-
"type": "extpoint",
|
|
180
|
-
"reqData": {
|
|
181
|
-
"keyword": normalized_keyword,
|
|
182
|
-
},
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
raw = _unwrap_route_raw(self._post(payload))
|
|
186
|
-
|
|
187
|
-
if raw.get("status") is False:
|
|
188
|
-
message = str(raw.get("message") or "remote api status=false")
|
|
189
|
-
error_code = raw.get("errorCode")
|
|
190
|
-
raise RuntimeError(f"{message} (errorCode={error_code})")
|
|
191
|
-
|
|
192
|
-
return self._normalize(raw, normalized_keyword)
|
|
193
|
-
|
|
194
|
-
@staticmethod
|
|
195
|
-
def _render_record_table(records: List[Any]) -> List[str]:
|
|
196
|
-
if not records:
|
|
197
|
-
return []
|
|
198
|
-
|
|
199
|
-
rows = [
|
|
200
|
-
"### [List] 拓展点列表",
|
|
201
|
-
"| # | 编码 | 名称 | 接口 / 类 | 对象 / 模块 | 示例 | 说明 |",
|
|
202
|
-
"| :--- | :--- | :--- | :--- | :--- | :--- | :--- |",
|
|
203
|
-
]
|
|
204
|
-
for idx, item in enumerate(records[:120], start=1):
|
|
205
|
-
if not isinstance(item, dict):
|
|
206
|
-
rows.append(
|
|
207
|
-
f"| {idx} | - | - | - | - | - | `{_md_escape(json.dumps(item, ensure_ascii=False))}` |"
|
|
208
|
-
)
|
|
209
|
-
continue
|
|
210
|
-
|
|
211
|
-
name = _pick_value(
|
|
212
|
-
item,
|
|
213
|
-
(
|
|
214
|
-
"name",
|
|
215
|
-
"extPointName",
|
|
216
|
-
"extpointName",
|
|
217
|
-
"pointName",
|
|
218
|
-
"title",
|
|
219
|
-
"sceneName",
|
|
220
|
-
"scenarioName",
|
|
221
|
-
"bizName",
|
|
222
|
-
),
|
|
223
|
-
)
|
|
224
|
-
number = _pick_value(item, ("number", "code", "sceneCode", "bizCode", "extPointCode"))
|
|
225
|
-
interface = _pick_value(
|
|
226
|
-
item,
|
|
227
|
-
(
|
|
228
|
-
"interface",
|
|
229
|
-
"interfaceName",
|
|
230
|
-
"fullClassName",
|
|
231
|
-
"className",
|
|
232
|
-
"clazz",
|
|
233
|
-
"apiClass",
|
|
234
|
-
"serviceInterface",
|
|
235
|
-
"serviceClass",
|
|
236
|
-
"classPath",
|
|
237
|
-
),
|
|
238
|
-
)
|
|
239
|
-
app = _pick_value(
|
|
240
|
-
item,
|
|
241
|
-
(
|
|
242
|
-
"app",
|
|
243
|
-
"appName",
|
|
244
|
-
"appId",
|
|
245
|
-
"module",
|
|
246
|
-
"moduleName",
|
|
247
|
-
"domain",
|
|
248
|
-
"product",
|
|
249
|
-
"productName",
|
|
250
|
-
"objectType",
|
|
251
|
-
),
|
|
252
|
-
)
|
|
253
|
-
desc = _pick_value(
|
|
254
|
-
item,
|
|
255
|
-
(
|
|
256
|
-
"description",
|
|
257
|
-
"desc",
|
|
258
|
-
"remark",
|
|
259
|
-
"memo",
|
|
260
|
-
"summary",
|
|
261
|
-
"scene",
|
|
262
|
-
"scenario",
|
|
263
|
-
"useScene",
|
|
264
|
-
),
|
|
265
|
-
)
|
|
266
|
-
sample_state = "✔️ 有" if _record_has_sample(item) else "—"
|
|
267
|
-
rows.append(
|
|
268
|
-
f"| {idx} | `{_md_escape(number)}` | {_md_escape(name)} | "
|
|
269
|
-
f"`{_md_escape(interface)}` | {_md_escape(app)} | {sample_state} | {_md_escape(desc)} |"
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
if len(records) > 120:
|
|
273
|
-
rows.append(
|
|
274
|
-
"\n> *结果较多,仅展示前 120 条;请缩小关键词。"
|
|
275
|
-
"只有需要生成代码或查看示例时才使用 --full。*"
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
return rows
|
|
279
|
-
|
|
280
|
-
def render(self, result: Dict[str, Any], full: bool = False) -> str:
|
|
281
|
-
if full:
|
|
282
|
-
return json.dumps(result, ensure_ascii=False, indent=2)
|
|
283
|
-
|
|
284
|
-
lines = [
|
|
285
|
-
"## [ExtPoint] 业务拓展点查询",
|
|
286
|
-
f"**关键词**: `{result.get('keyword') or '-'}`",
|
|
287
|
-
f"**命中数**: `{result.get('count')}`",
|
|
288
|
-
f"**hasSample**: `{str(bool(result.get('hasSample'))).lower()}`",
|
|
289
|
-
]
|
|
290
|
-
total = result.get("total")
|
|
291
|
-
if total is not None:
|
|
292
|
-
lines.append(f"**远端 total**: `{total}`")
|
|
293
|
-
trace_id = result.get("traceId")
|
|
294
|
-
if trace_id:
|
|
295
|
-
lines.append(f"**traceId**: `{trace_id}`")
|
|
296
|
-
|
|
297
|
-
records = result.get("records")
|
|
298
|
-
if isinstance(records, list) and records:
|
|
299
|
-
lines.append("")
|
|
300
|
-
lines.extend(self._render_record_table(records))
|
|
301
|
-
else:
|
|
302
|
-
lines.append("")
|
|
303
|
-
lines.append("> 未从返回数据中识别出拓展点列表,以下输出原始 data 便于判断接口结构。")
|
|
304
|
-
lines.append("```json")
|
|
305
|
-
lines.append(json.dumps(result.get("data"), ensure_ascii=False, indent=2))
|
|
306
|
-
lines.append("```")
|
|
307
|
-
|
|
308
|
-
lines.append(
|
|
309
|
-
"\n> 下一步:需要生成代码或查看示例时加 `--full`。"
|
|
310
|
-
"如果示例内容足够清晰,可先按示例实现;示例缺失/不完整/签名不确定时,再用 "
|
|
311
|
-
"`cosmic-api-knowledge.py detail <full.class.Name>` 确认方法签名。"
|
|
312
|
-
)
|
|
313
|
-
return "\n".join(lines)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
def _load_config_for_query(config_path: Optional[str]) -> Dict[str, Any]:
|
|
317
|
-
"""
|
|
318
|
-
Keep standard ok-cosmic config behavior when possible, but allow this online
|
|
319
|
-
query tool to run with explicit --api-url / environment variables if the
|
|
320
|
-
implicit cwd config is absent.
|
|
321
|
-
Explicit --config still remains strict.
|
|
322
|
-
"""
|
|
323
|
-
try:
|
|
324
|
-
return load_project_config(config_path)
|
|
325
|
-
except FileNotFoundError:
|
|
326
|
-
if config_path:
|
|
327
|
-
raise
|
|
328
|
-
return {
|
|
329
|
-
"__config_path__": "",
|
|
330
|
-
"__config_dir__": os.getcwd(),
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
def main():
|
|
335
|
-
parser = FriendlyArgumentParser(
|
|
336
|
-
description="Cosmic ExtPoints Query CLI — 苍穹业务拓展点在线查询",
|
|
337
|
-
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
338
|
-
epilog="""\
|
|
339
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
340
|
-
推荐用法
|
|
341
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
342
|
-
# 按关键词查询业务拓展点
|
|
343
|
-
%(prog)s --config ok-cosmic.json get --keyword 应付
|
|
344
|
-
|
|
345
|
-
# keyword 也可作为位置参数
|
|
346
|
-
%(prog)s --config ok-cosmic.json get 应付
|
|
347
|
-
|
|
348
|
-
# 需要生成代码或查看示例时,输出完整 JSON
|
|
349
|
-
%(prog)s --config ok-cosmic.json get --keyword 应付 --full
|
|
350
|
-
|
|
351
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
352
|
-
AI 调用约束
|
|
353
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
354
|
-
- 本脚本只负责定位业务拓展点候选。
|
|
355
|
-
- 摘要和 --full 都会输出 hasSample,便于判断是否需要查看完整示例。
|
|
356
|
-
- 默认不要加 --full;只有需要生成实现代码或查看示例时才使用 --full。
|
|
357
|
-
- --full 返回中示例足够清晰时,可先按示例实现;示例缺失/不完整/签名不确定时再用 cosmic-api-knowledge.py detail 确认方法签名。
|
|
358
|
-
- 统一路由请求体固定为 {"data": {"type": "extpoint", "reqData": {"keyword": "..."}}}。
|
|
359
|
-
""",
|
|
360
|
-
)
|
|
361
|
-
parser.add_argument("--config", help="Path to ok-cosmic.json")
|
|
362
|
-
parser.add_argument("--api-url", help="Override extpoints API URL for this invocation")
|
|
363
|
-
parser.add_argument("--debug", action="store_true")
|
|
364
|
-
|
|
365
|
-
sub_parser = parser.add_subparsers(dest="command")
|
|
366
|
-
get_parser = sub_parser.add_parser("get")
|
|
367
|
-
get_parser.add_argument("keyword_arg", nargs="?", help="业务关键词(也可用 --keyword)")
|
|
368
|
-
get_parser.add_argument("--keyword", help="业务关键词,例如:应付")
|
|
369
|
-
get_parser.add_argument("--full", action="store_true", help="需要生成代码或查看示例时,直接输出完整 JSON")
|
|
370
|
-
|
|
371
|
-
args = parser.parse_args()
|
|
372
|
-
if args.command != "get":
|
|
373
|
-
parser.print_help()
|
|
374
|
-
return
|
|
375
|
-
|
|
376
|
-
keyword = (args.keyword or args.keyword_arg or "").strip()
|
|
377
|
-
|
|
378
|
-
try:
|
|
379
|
-
config = _load_config_for_query(args.config)
|
|
380
|
-
query = ExtPointsQuery(config, api_url=args.api_url, debug=args.debug)
|
|
381
|
-
result = query.query(keyword=keyword)
|
|
382
|
-
print(query.render(result, full=args.full))
|
|
383
|
-
except Exception as e:
|
|
384
|
-
print(f"✖️ 错误: {str(e)}", file=sys.stderr)
|
|
385
|
-
sys.exit(1)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if __name__ == "__main__":
|
|
389
|
-
sys.exit(run_cli(main))
|